package cn.tannn.surenessdemo.controller;

import cn.hutool.core.lang.tree.Tree;
import cn.jdevelops.annotation.mapping.PathRestController;
import cn.jdevelops.entity.basics.vo.SerializableVO;
import cn.jdevelops.exception.annotation.DisposeException;
import cn.jdevelops.result.result.ResultVO;
import cn.tannn.surenessdemo.constant.HeaderConstant;
import cn.tannn.surenessdemo.controller.dto.SettingUserStatusDTO;
import cn.tannn.surenessdemo.controller.vo.AuthUserVO;
import cn.tannn.surenessdemo.user.service.AccountService;
import cn.tannn.surenessdemo.user.service.AuthRouteService;
import cn.tannn.surenessdemo.util.JwtTokenUtil;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.usthe.sureness.subject.SubjectSum;
import com.usthe.sureness.util.SurenessContextHolder;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;

import static cn.tannn.surenessdemo.constant.HeaderConstant.HEADER_USERNAME;

/**
 * 用户管理
 *
 * @author tnnn
 * @version V1.0
 * @date 2022-07-18 13:42
 */
@PathRestController("user")
@Slf4j
@Api(tags = "用户管理", value = "用户管理")
@RequiredArgsConstructor
@ApiSupport(order = 2)
public class UserController {

    /**
     * 用户
     */
    private final AccountService accountService;
    private final AuthRouteService authRouteService;



    @ApiOperation(value = "获取用户角色(登录信息获取", notes = "用户管理")
    @GetMapping("/role")
    @ApiOperationSupport(order = 1)
    public ResultVO<List<String>> getUserRoles() {
        // todo 从资源树中获取数据
        // todo token 解析
        SubjectSum subject = SurenessContextHolder.getBindSubject();
        if (subject == null || subject.getPrincipal() == null) {
            return ResultVO.fail("暂为查询到角色，请设置该用户角色");
        }
        String username = (String) subject.getPrincipal();
        List<String> roles = accountService.loadAccountRoles(username);
        return ResultVO.successForData(roles);
    }

    @ApiOperation(value = "设置用户角色", notes = "用户管理")
    @PostMapping("/authority/role/add")
    @ApiOperationSupport(order = 2)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户登录名", type = "String", paramType = "query"),
            @ApiImplicitParam(name = "roleCode", value = "角色code", type = "String", paramType = "query"),
    })
    @DisposeException(messages = "当前用户已经拥有此角色，请勿重复设置", exceptions = SQLIntegrityConstraintViolationException.class)
    public ResultVO<String> authorityUserRole(
            @RequestParam @NotBlank String username,
            @RequestParam @NotBlank String roleCode) {
        boolean flag = accountService.authorityUserRole(username, roleCode);
        return flag ? ResultVO.success("角色设置成功") : ResultVO.fail("角色已分配给当前用户");
    }


    @ApiOperation(value = "删除用户的角色", notes = "用户管理")
    @PostMapping("/authority/role/delete")
    @ApiOperationSupport(order = 3)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "username", value = "用户登录名", type = "String", paramType = "query"),
            @ApiImplicitParam(name = "roleCode", value = "角色code", type = "String", paramType = "query"),
    })
    public ResultVO<String> deleteAuthorityUserRole(
            @RequestParam @NotBlank String username,
            @RequestParam @NotBlank String roleCode) {
        accountService.deleteAuthorityUserRole(username, roleCode);
        return ResultVO.success("角色删除成功");
    }


    @ApiOperation(value = "查询所有用户", notes = "用户管理")
    @PostMapping("finAll")
    @ApiOperationSupport(order = 4)
    public ResultVO<List<AuthUserVO>> findAll() {
        return ResultVO.success(SerializableVO.to(accountService.findAll(), AuthUserVO.class), "角色查询成功");
    }

    /**
     * 用户状态(1.正常 2.锁定 3.删除 4.非法)
     *
     * @return ResultVO
     */
    @ApiOperation(value = "设置用户状态", notes = "用户管理")
    @PostMapping("settingUserStatus")
    @ApiOperationSupport(order = 4)
    public ResultVO<String> settingUserStatus(@RequestBody @Valid SettingUserStatusDTO settingUserStatus) {
        accountService.settingStatus(settingUserStatus.getUsername(), settingUserStatus.getStatus());
        return ResultVO.success();
    }

    @ApiOperation(value = "获取当前登录的用户信息", notes = "支持两种方式，1:CustomHeaderTokenSubjectCreator，" +
            "2:CustomPasswdSubjectCreator。一般能进来就是有效用户（此接口一定需要登录后才能访问，即最基础的权限")
    @PostMapping("getLoginUser")
    @ApiOperationSupport(order = 5)
    public ResultVO<AuthUserVO> getLoginUser(HttpServletRequest request) {
        String token = request.getHeader(HeaderConstant.HEADER_TOKEN);
        String username;
        if (StringUtils.isBlank(token)) {
            username = request.getHeader(HEADER_USERNAME);
        } else {
            Claims claims = JwtTokenUtil.parseJwtNoExpiredJwtException(token);
            username = claims.getSubject();
        }
        // 可以考虑从redis中拿。但是每次修改用户相关的数据时都要更新一份到redis中
        return ResultVO.successForData(accountService.getUser(username));
    }



    /**
     * 获取当前用户的路由树
     */
    @ApiOperation(value = "获取当前用户的路由树", notes = "用户管理")
    @GetMapping("userRouteTree")
    @ApiOperationSupport(order = 5)
    public ResultVO<List<Tree<String>>> userRouteTree(String username){
        List<Tree<String>> trees = authRouteService.userRouteTrue(accountService.getUser(username).getCode());
        return ResultVO.successForData(trees);
    }


}
